package com.czy.model;

import lombok.Getter;
import lombok.Setter;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;

/**
 * 请求封装
 * @author czy
 * @date 2021-5-26 15:43
 */
@Getter
@Setter
public class Request {
    /**换行*/
    private static final String CRLF="\r\n";
    /**空格*/
    private static final String BLANK=" ";

    /**输入流*/
    private InputStream is;

    /**请求字符串,请求方式，请求的路径，参数，协议，协议版本，请求的正文。。。*/
    private String requestInfo;

    /**请求的方式*/
    private String method;

    /**请求的url*/
    private String url;

    /**参数*/
    private Map<String, List<String>> parametermapValues;

    public Request() {
        parametermapValues=new HashMap<String,List<String>>();
        method="";
        url="";
        requestInfo="";
    }
    public Request(InputStream is){
        this();//调用本类无参的构造方法
        this.is=is;
        try {
            byte [] buf=new byte[2048];
            int len=this.is.read(buf);
            requestInfo=new String(buf,0,len);
        } catch (IOException e) {
            return;
        }
        //调用本类中的分解请求信息的方法
        this.parseRequestInfo();
    }

    //分解请求信息的方法
    /**
     * 请求方式
     * 请求路径
     * 请求的参数
     *
     */
    private void parseRequestInfo(){
        String paraString="";//用于存储请求参数
        //获取请求参数的第一行
        String firstLine=requestInfo.substring(0, requestInfo.indexOf(CRLF)).trim();//从0开始，到第一个换行的位置
        //分解出请求方式
        int index=firstLine.indexOf("/");
        this.method=firstLine.substring(0, index).trim();
        //分解url  ,get可能包含参数，也可能不包含参数post
        String urlString= firstLine.substring(index,firstLine.indexOf("HTTP/")).trim();
        //判断请求方式是GET还 是POST
        if("get".equalsIgnoreCase(this.method)){  //包含请求参数
            if (urlString.contains("?")) {
                String [] urlArray=urlString.split("\\?");
                this.url=urlArray[0];
                paraString=urlArray[1];
            }else{
                this.url=urlString;
            }
        }else{//post不包含请求参数
            this.url=urlString;
            paraString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
        }
        if (paraString.equals("")) {
            return;
        }
        //请求参数
        //System.out.println(paraString);

        //调用本类的中的分析请求参数的方法
        this.parseParam(paraString);

    }

    /**
     * username=bjsxt
     * pwd=123
     * hobby=ball
     * hobby=paint
     *
     * username=
     * @param paramString
     */
    private void parseParam(String paramString){
        String [] token=paramString.split("&");
        for(int i=0;i<token.length;i++){
            String keyValues=token[i];  //username=fasaf
            //继续分割
            String[] keyValue=keyValues.split("=");  //username=
            if (keyValue.length==1) {
                keyValue= Arrays.copyOf(keyValue, 2);
                keyValue[1]=null;
            }
            //转成Map集合
            String key=keyValue[0].trim();
            String value=keyValue[1]==null?null:decode(keyValue[1].trim(), "utf-8");
            //放到参数的集合中存储
            if (!parametermapValues.containsKey(key)) {
                parametermapValues.put(key, new ArrayList<String>());
            }
            List<String> values=parametermapValues.get(key);
            values.add(value);
        }
    }
    /**
     * 编写根据表单元素的name获取多个对应的值
     *
     */
    public String [] getParamterValues(String name){
        List<String> values=parametermapValues.get(name);
        if (values==null) {
            return null;
        }else{
            return values.toArray(new String [0]);
        }

    }
    /**
     * 根据表单元素的name获取单个值
     *
     */
    public String  getParameter(String name){
        //调用根据名称获取多个值的方法
        String [] values=getParamterValues(name);
        if (values==null) {
            return null;
        }else{
            return values[0];
        }
    }
    //用于测试
    public static void main(String[] args) {
        Request req=new Request();
        //调用分解参数的方法
        req.parseParam("username=%E5%8C%97%E4%BA%AC%E5%B0%9A%E5%AD%A6%E5%A0%82&pwd=123&hobby=ball&hobby=paint");
        System.out.println(req.parametermapValues);

        //调用获取多个值的方法
        String [] str=req.getParamterValues("hobby");
        for (String string : str) {
            System.out.println(string);
        }
        //调用获取单个值的方法
        System.out.println(req.getParameter("pwd"));
    }

    /**
     * 处理中文，因为浏览器对中文进行了编码，进行解码
     * @param value
     * @param code
     * @return
     */
    private String decode(String value, String code){
        try {
            return URLDecoder.decode(value,code);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

}
